package com.dge.common.base.presenter

import android.app.Activity
import android.content.Context
import androidx.fragment.app.Fragment
import com.dge.common.base.baseModel.MvpModel
import com.dge.common.base.view.MvpView
import timber.log.Timber
import java.lang.ref.SoftReference
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

open class BasePresenter<V : MvpView, M : MvpModel> : MvpPresenter {
    private var mReferenceView: SoftReference<V>? = null

    @JvmField
    var context: Context? = null

    @JvmField
    var view: V? = null

    @JvmField
    var model: M? = null
    override fun attachView(view: MvpView) {
        mReferenceView = SoftReference(view as V) //软引用，防止内存泄漏
        this.view = mReferenceView!!.get() as V
        //动态代理：可以做到统一的空类型判断
//        this.view = Proxy.newProxyInstance(
//            view.javaClass.classLoader,
//            view.javaClass.interfaces
//        ) { proxy, method, args ->
//            if (mReferenceView == null || mReferenceView!!.get() == null) {
//                null
//            } else method?.invoke(mReferenceView!!.get(), args)
//        } as V
        if (this.view is Activity) context = this.view as Context
        else if (this.view is Fragment) context = (this.view as Fragment).activity
        //通过获得泛型类的父类，拿到泛型的接口类实例，通过反射来实例化 model
        val type = this.javaClass.genericSuperclass as? ParameterizedType
        if (type != null) {
            val types: Array<Type> = type.actualTypeArguments
            Timber.d("types.size = ${types.size}")
            try {
                model = (types[1] as Class<*>).newInstance() as M
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: InstantiationException) {
                e.printStackTrace()
            }
        }
    }

    override fun detachView() {
        mReferenceView?.clear();
        mReferenceView = null;
    }

    override fun isAttached(): Boolean {
        return mReferenceView != null && mReferenceView?.get() != null
    }
}